from CDB import CDB


class FPAdder:
    def __init__(self, cdb: CDB):
        self.busy = False            # 标志单元是否忙碌
        self.delay_time = 2          # 浮点加法需要的周期数
        self.instruction = None      # 执行的指令
        self.current_clock = 0       # 当前的时钟周期
        self.start_clock = 0         # 开始时的时钟周期
        self.cdb = cdb

    def issue_instr(self, instruction, current_clock): 
        """
        发送指令到浮点加法单元执行。
        """
        if not self.busy:
            self.instruction = instruction
            self.start_clock = current_clock
            self.current_clock = current_clock
            self.busy = True

    def execute(self):
        """
        执行浮点加法运算，检查是否达到延迟时间并执行。
        """
        if not self.busy:
            return None  
        # 递增当前时钟周期
        self.current_clock += 1

        # 检查是否达到了加法运算的延迟时间，并且CDB是否空闲
        if self.current_clock - self.start_clock >= self.delay_time and not self.cdb.busy:
            # 执行浮点加法运算并广播结果
            return self.perform_addition_and_broadcast()
        return None

    def perform_addition_and_broadcast(self):
        """
        执行浮点加法运算并广播结果。
        """
        # 重置忙碌状态
        self.busy = False

        # 从当前指令中获取条目编号，并广播结果
        entry = self.instruction["Entry"]
        self.cdb.broadcast(entry, 1)
        return 1  # 表示成功

class FPMultiplier:
    def __init__(self, cdb: CDB):
        # 浮点乘法运算单元的基本属性
        self.busy = False                # 标志单元是否忙碌
        self.operation_delays = {'MULTD': 6, 'DIVD': 12}  # 乘法和除法的周期数
        self.instruction = None                # 执行的指令
        self.current_clock = 0           # 当前的时钟周期
        self.start_clock = 0             # 开始时的时钟周期
        self.cdb = cdb

    def issue_instr(self, instruction, current_clock):
        """
        发送指令到浮点乘法运算单元执行。
        """
        if not self.busy:
            self.instruction = instruction
            self.start_clock = current_clock
            self.current_clock = current_clock
            self.busy = True

    def execute(self):
        """
        执行浮点乘法运算，检查是否达到延迟时间并执行。
        """
        if not self.busy:
            return None
        # 递增当前时钟周期
        self.current_clock += 1

        # 获取指令中的操作类型
        operation = self.instruction["Instruction"].split()[0].upper()
        # 获取对应操作的延迟时间
        cycle_delay = self.operation_delays.get(operation, 6)

        # 检查是否达到了乘法运算的延迟时间，并且CDB是否空闲
        if self.current_clock - self.start_clock >= cycle_delay and not self.cdb.busy:
            # 执行浮点乘法运算并广播结果
            return self.perform_multiplication_and_broadcast()
        return None

    def perform_multiplication_and_broadcast(self):
        """
        执行浮点乘法运算并广播结果。
        """
        # 重置忙碌状态
        self.busy = False

        # 从当前指令中获取条目编号，并广播结果
        entry = self.instruction["Entry"]
        self.cdb.broadcast(entry, 1)
        return 1  # 表示成功
